<!DOCTYPE html>
<html>

<head>
    <title>SunBurst</title>
    <script src="d3.min.js"></script>
</head>

<body>
    <svg width="1600" height="1000" id="mainsvg" class="svgs" style="display: block; margin: auto;"></svg>
    <script>
        const svg = d3.select('#mainsvg');
        const width = +svg.attr('width');
        const height = +svg.attr('height');
        const g = svg.append('g')
            .attr('transform', `translate(${width / 2}, ${height / 2})`);
        let root;

        const arc = d3.arc()
            .startAngle(d => d.x0)
            .endAngle(d => d.x1)
            // pad distances equal to padAngle * padRadius; 
            // It's split into two parameters 
            // so that the pie generator doesn't need to concern itself with radius
            .padAngle(d => Math.min((d.x1 - d.x0) / 2, 0.005))
            //.padRadius(radius / 2)
            .innerRadius(d => d.y0)
            .outerRadius(d => d.y1)

        const render = function (data) {
            const color = d3.scaleOrdinal(d3.schemeCategory10)
            const fill = d => {
                while (d.depth > 1)
                    d = d.parent;
                return color(d.data.name);
            };

            g.selectAll('.datapath')
            // this can be simplified as .data(root.descendants().filter(d => d.depth))
            .data(root.descendants().filter(d => d.depth !== 0))
            .join('path')
            .attr('class', 'datapath')
            .attr("fill", fill)
            .attr("d", arc)

            g.selectAll('.datatext')
            .data(root.descendants()
            .filter(d => d.depth && (d.x1 - d.x0) > Math.PI / 65 && d.data.name.length < 15))
            //.filter(d => d.depth))
            .join("text")
            .attr('class', 'datatext')
            .attr("pointer-events", "none")
            .attr("text-anchor", "middle")
            .attr('font-size', d => d.data.name.length < 15 ? '1em' : '.85em')
            .attr("transform", function (d) {
                const x = (d.x0 + d.x1) / 2 * 180 / Math.PI;
                const y = (d.y0 + d.y1) / 2;
                // note that there is an implicit transform inherited from the maingroup; 
                return `rotate(${x - 90}) translate(${y},0) rotate(${x < 180 ? 0 : 180}) translate(0, 5)`;
            })
            // the following code is alternative to the 'translate(0, 5) above; '
            //.attr("dy", "0.35em")
            .text(d => d.data.name)
        }

        d3.json('xinjiang.json').then(data => {
            root = d3.partition().size([2 * Math.PI, 500])
                (d3.hierarchy(data).sum(d => d.population)
                    .sort((a, b) => b.population - a.population));
            render(root);
        });

    </script>
</body>

</html>